﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using Sustainalytics.DataLayer.ConnectionStrings;
using Sustainalytics.DataLayer.Shared;
using Sustainalytics.Entities;
using Sustainalytics.Entities.ConnectionStrings;
using Sustainalytics.Entities.Governance;
using Sustainalytics.Governance.Service.Dto;
using Sustainalytics.Utils;
using System.Web.Http.Cors;

namespace Sustainalytics.Governance.Service.Controllers
{
    [EnableCors(origins: "*", headers: "*", methods: "*")]
    [RoutePrefix("api/v1/company")]
    public class GovernanceKeyCgIssuesController:ApiController
    {
        private readonly IRepositoryCollection<GovernanceIssue> _repositoryIssues;
        private readonly IRepositoryCollection<GovernanceComputationResult> _repositoryComputation; 

        public GovernanceKeyCgIssuesController()
        {
            var connectionString = ConfigurationManager.ConnectionStrings["ClientPlatform"].ConnectionString;
            var connectionStringsManager =
                ConnectionStringsManager.GetInstance(ConnectionStringsRepository.GetInstance(connectionString));
            _repositoryIssues=new RepositoryCollection<GovernanceIssue>(connectionStringsManager.GetConnectionString(ConnectionStringType.GovernanceDW));
            _repositoryComputation=new RepositoryCollection<GovernanceComputationResult>(connectionStringsManager.GetConnectionString(ConnectionStringType.GovernanceDW));
        }

        [Route("{companyId}/cgissues")]
        public HttpResponseMessage Get([FromUri] Guid companyId, [FromUri]bool overallScores=false)
        {
            try
            {
                var issues = _repositoryIssues.ReadAllWhere(a => a.CompanyId == companyId, null, null,
                    Ordering<GovernanceIssue>.Ascending(a => a.Number)).OrderBy(a=>a.Number).ToList();
                var compResults =
                    _repositoryComputation.ReadAllWhere(a => a.Id == companyId, skip: 0, take: 1).FirstOrDefault();
                foreach (var governanceIssue in issues)
                {
                    var issue = compResults.IssuesPerformance.FirstOrDefault(a => a.Number == governanceIssue.Number);
                    if (issue != null)
                    {
                        governanceIssue.Score = ScoreConversion.GetRoundedScore(issue.Score);
                    }
                }

                if (overallScores)
                {
                    var overall=new CompanyKeyGovernanceIssueOveralScoresDto(){CompanyId = companyId};
                   //overall.OverallScores
                    overall.OverallScores=new IssuesBaseDto[issues.Count];
                    for (int i = 0; i < overall.OverallScores.Length; i++)
                    {
                        var current = issues[i];
                        overall.OverallScores[i]=new IssuesBaseDto()
                        {
                            CompanyId = companyId,
                            Name =current.Name,
                            Score = current.Score
                        };
                    }
                    return Request.CreateResponse(HttpStatusCode.OK, overall);
                }

                var arrIssue = MapCompanyKeyGovernanceIssueDtos(companyId, issues);
                return Request.CreateResponse(HttpStatusCode.OK, arrIssue);
            }
            catch (Exception ex)
            {
                GovernanceEventSource.Log.LogError(ex);
                return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "An uhandlded exception occurred");
            }
        }



        [Route("{companyId}/cgissues/{issueid}/indicators")]
        public HttpResponseMessage Get([FromUri] Guid companyId, [FromUri] string issueid)
        {
            try
            {
                var compResult =
                    _repositoryComputation.ReadAllWhere(a => a.Id == companyId, skip: 0, take: 1).FirstOrDefault();
                var issue =
                    _repositoryIssues.ReadAllWhere(a => a.CompanyId == companyId && a.Number == issueid)
                        .FirstOrDefault();

                var foundComputation = compResult.IssuesPerformance.FirstOrDefault(a => a.Number == issueid);
                var compIssueDto = new CompanyGovernanceIssueDto() { CompanyId = companyId };
                compIssueDto.Issue = new IssueDataDto()
                {
                    CompanyId = companyId,
                    AssesmentType = (int)foundComputation.Assessment,
                    Name = foundComputation.Name,
                    Score = ScoreConversion.GetRoundedScore(foundComputation.Score)
                };
                if (issue.Outlook.HasValue)
                {
                    compIssueDto.Issue.Outlook = (int?)issue.Outlook.Value;
                }
                if (!string.IsNullOrWhiteSpace(issue.Comment))
                {
                    compIssueDto.Issue.Comment = issue.Comment;
                }
                var performanceRegion =
                    foundComputation.Performances.FirstOrDefault(a => a.PerformanceType == PerformanceType.Region);
                compIssueDto.Percentile = ScoreConversion.GetRoundedScore(performanceRegion.Percentile);
                compIssueDto.ComparativeGroupRank = performanceRegion.Rank.ToString();
                compIssueDto.ComparativeGroupSize = performanceRegion.GroupCount.ToString();
                compIssueDto.Weight = foundComputation.Weight.ToString("P0");


                return Request.CreateResponse(HttpStatusCode.OK, compIssueDto);
            }
            catch (Exception ex)
            {
                GovernanceEventSource.Log.LogError(ex);
                return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "An unhandled exception occurred");

            }
        }

        private static CompanyKeyGovernanceIssueDto[] MapCompanyKeyGovernanceIssueDtos(Guid companyId, IList<GovernanceIssue> issues)
        {
            var arrIssue = new CompanyKeyGovernanceIssueDto[issues.Count];
            for (int i = 0; i < issues.Count; i++)
            {
                var current = issues[i];
                arrIssue[i] = new CompanyKeyGovernanceIssueDto()
                {
                    CompanyId = current.CompanyId,
                    Issue =
                        new IssueDataDto()
                        {
                            CompanyId = current.CompanyId,
                            Name = current.Name,
                            Score = current.Score,
                            Number = current.Number,
                            Comment = current.Comment
                        },
                };
                if (current.Outlook.HasValue)
                {
                    arrIssue[i].Issue.Outlook = (int?) current.Outlook.Value;
                }
                arrIssue[i].CompanyIndicators = new IndicatorDataDto[current.Indicators.Count];
                for (int j = 0; j < arrIssue[i].CompanyIndicators.Length; j++)
                {
                    var indicatorCurrent = current.Indicators[j];
                    arrIssue[i].CompanyIndicators[j] = new IndicatorDataDto()
                    {
                        CompanyId = companyId,
                        Name = indicatorCurrent.Name,
                        Number = indicatorCurrent.Number,
                        Score = indicatorCurrent.Score,
                        IssueName = current.Number,
                        Id = indicatorCurrent.Id
                    };
                    if (indicatorCurrent.Outlook.HasValue)
                    {
                        arrIssue[i].CompanyIndicators[j].Outlook = indicatorCurrent.Outlook.Value;
                    }
                }
                Array.Sort(arrIssue[i].CompanyIndicators,
                    (dto, dataDto) =>
                    {
                        var dtoNumber = Convert.ToInt32(dto.Number.Substring(5));
                        var dataDtoNumber = Convert.ToInt32(dataDto.Number.Substring(5));
                        return dtoNumber.CompareTo(dataDtoNumber);
                    });
            }
            return arrIssue;
        }
    }
}
